package com.ferry.transport.api.config;

import com.ferry.common.util.constant.AbstractConstant;
import com.ferry.common.util.constant.ConstantPool;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by daiyong
 */
public final class TcpOption<T> extends AbstractConstant<TcpOption<T>> {

	private static final ConstantPool<TcpOption<Object>> pool = new ConstantPool<TcpOption<Object>>() {
		@Override
		protected TcpOption<Object> newConstant(int id, String name) {
			return new TcpOption<>(id, name);
		}
	};

	public static <T> TcpOption<T> valueOf(String name) {
		return (TcpOption<T>) pool.valueOf(name);
	}

	public static <T> TcpOption<T> valueOf(Class<?> firstNameComponent, String secondNameComponent) {
		return (TcpOption<T>) pool.valueOf(firstNameComponent, secondNameComponent);
	}

	public static <T> TcpOption<T> newInstance(String name) {
		return (TcpOption<T>) pool.newInstance(name);
	}

	public static boolean exists(String name) {
		return pool.exists(name);
	}

	public static final Set<TcpOption<?>> ALL_OPTIONS;
	public static final TcpOption<Boolean> TCP_NODELAY = valueOf("TCP_NODELAY");
	public static final TcpOption<Boolean> KEEP_ALIVE = valueOf("KEEP_ALIVE");
	public static final TcpOption<Boolean> SO_REUSEADDR = valueOf("SO_REUSEADDR");
	public static final TcpOption<Integer> SO_SNDBUF = valueOf("SO_SNDBUF");
	public static final TcpOption<Integer> SO_RCVBUF = valueOf("SO_RCVBUF");
	public static final TcpOption<Integer> SO_LINGER = valueOf("SO_LINGER");
	public static final TcpOption<Integer> SO_BACKLOG = valueOf("SO_BACKLOG");
	public static final TcpOption<Integer> IP_TOS = valueOf("IP_TOS");
	public static final TcpOption<Boolean> ALLOW_HALF_CLOSURE = valueOf("ALLOW_HALF_CLOSURE");
	public static final TcpOption<Integer> WRITE_BUFFER_HIGH_WATER_MARK = valueOf("WRITE_BUFFER_HIGH_WATER_MARK");
	public static final TcpOption<Integer> WRITE_BUFFER_LOW_WATER_MARK = valueOf("WRITE_BUFFER_LOW_WATER_MARK");
	public static final TcpOption<Integer> IO_RATIO = valueOf("IO_RATIO");
	public static final TcpOption<Integer> CONNECT_TIMEOUT_MILLIS = valueOf("CONNECT_TIMEOUT_MILLIS");
	public static final TcpOption<Boolean> SO_REUSEPORT = valueOf("SO_REUSEPORT");
	public static final TcpOption<Boolean> TCP_CORK = valueOf("TCP_CORK");
	public static final TcpOption<Long>    TCP_NOTSENT_LOWAT = valueOf("TCP_NOTSENT_LOWAT");
	public static final TcpOption<Integer> TCP_KEEPIDLE = valueOf("TCP_KEEPIDLE");
	public static final TcpOption<Integer> TCP_KEEPINTVL = valueOf("TCP_KEEPINTVL");
	public static final TcpOption<Integer> TCP_KEEPCNT = valueOf("TCP_KEEPCNT");
	public static final TcpOption<Integer> TCP_USER_TIMEOUT = valueOf("TCP_USER_TIMEOUT");
	public static final TcpOption<Boolean> IP_FREEBIND = valueOf("IP_FREEBIND");
	public static final TcpOption<Boolean> IP_TRANSPARENT = valueOf("IP_TRANSPARENT");
	public static final TcpOption<Integer> TCP_FASTOPEN = valueOf("TCP_FASTOPEN");
	public static final TcpOption<Boolean> TCP_FASTOPEN_CONNECT = valueOf("TCP_FASTOPEN_CONNECT");
	public static final TcpOption<Integer> TCP_DEFER_ACCEPT = valueOf("TCP_DEFER_ACCEPT");
	public static final TcpOption<Boolean> TCP_QUICKACK = valueOf("TCP_QUICKACK");
	public static final TcpOption<Boolean> EDGE_TRIGGERED = valueOf("EDGE_TRIGGERED");
	
	static {
		Set<TcpOption<?>> options = new HashSet<>();

		options.add(TCP_NODELAY);
		options.add(KEEP_ALIVE);
		options.add(SO_REUSEADDR);
		options.add(SO_SNDBUF);
		options.add(SO_RCVBUF);
		options.add(SO_LINGER);
		options.add(SO_BACKLOG);
		options.add(IP_TOS);
		options.add(ALLOW_HALF_CLOSURE);
		options.add(WRITE_BUFFER_HIGH_WATER_MARK);
		options.add(WRITE_BUFFER_LOW_WATER_MARK);
		options.add(IO_RATIO);
		options.add(CONNECT_TIMEOUT_MILLIS);
		options.add(SO_REUSEPORT);
		options.add(TCP_CORK);
		options.add(TCP_NOTSENT_LOWAT);
		options.add(TCP_KEEPIDLE);
		options.add(TCP_KEEPINTVL);
		options.add(TCP_USER_TIMEOUT);
		options.add(IP_FREEBIND);
		options.add(IP_TRANSPARENT);
		options.add(TCP_FASTOPEN);
		options.add(TCP_FASTOPEN_CONNECT);
		options.add(TCP_DEFER_ACCEPT);
		options.add(TCP_QUICKACK);
		options.add(EDGE_TRIGGERED);

		ALL_OPTIONS = Collections.unmodifiableSet(options);
	}

	private TcpOption(int id, String name) {
		super(id, name);
	}
}
